package com.wutong.eams.other;

import com.wutong.eams.enums.RequestMethod;
import com.wutong.eams.exception.RouterException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.function.Function;

@Slf4j
public class Router {

    private Router() {
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class HttpServletMethod {
        private HttpServletRequest request;
        private HttpServletResponse response;
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class RouteAttribute {
        private RequestMethod method;
        private String contentType;
        private String targetUrl;
        private Function<HttpServletMethod, Void> handler;
    }

    public interface Handler {
        Router add(Function<HttpServletMethod, Void> handler);
    }

    @Getter
    private static final Map<String, List<RouteAttribute>> routeMap = new HashMap<>();

    private static Router instance;

    public static Router of() {
        if (instance == null) {
            instance = new Router();
        }
        return instance;
    }

    public Router add(String originUrl, RouteAttribute routeAttribute) {
        if (!routeMap.containsKey(originUrl)) {
            routeMap.put(originUrl, new ArrayList<>());
        } else if (routeMap.get(originUrl).hashCode() != routeAttribute.hashCode()) {
            routeMap.get(originUrl).add(routeAttribute);
        } else {
            log.warn("路由配置已存在: {} {} {} {}", originUrl, routeAttribute.getMethod(), routeAttribute.getContentType(), routeAttribute.getTargetUrl());
        }
        log.info("添加路由配置: {} {} {} {}", originUrl, routeAttribute.getMethod(), routeAttribute.getContentType(), routeAttribute.getTargetUrl());
        return this;
    }

    public Router add(String originUrl, String method, String contentType, String targetUrl, Function<HttpServletMethod, Void> handler) {
        return add(originUrl, new RouteAttribute(RequestMethod.valueOf(method), contentType, targetUrl, handler));
    }


    public Handler add(String originUrl, String method, String contentType, String targetUrl) {
        add(originUrl, method, contentType, targetUrl, null);
        return handler -> {
            RouteAttribute routeAttribute = routeMap.get(originUrl).stream()
                    .filter(r -> r.getMethod().getValue().equals(method) && r.getContentType().equals(contentType))
                    .findFirst()
                    .orElseThrow(() -> new RouterException("未找到对应的路由配置: " + originUrl + " " + method + " " + contentType));
            routeAttribute.setHandler(handler);
            return Router.this;
        };
    }

    public Handler add(String originUrl, RequestMethod method, String contentType, String targetUrl) {
        return add(originUrl, method.getValue(), contentType, targetUrl);
    }

    public void addHandler(String originUrl, String method, String contentType, String targetUrl, Function<HttpServletMethod, Void> handler) {
        if (!routeMap.containsKey(originUrl)) {
            add(originUrl, method, contentType, targetUrl, handler);
        } else {
            RouteAttribute routeAttribute = routeMap.get(originUrl).stream()
                    .filter(r -> r.getMethod().getValue().equals(method) && r.getContentType().equals(contentType) && r.getTargetUrl().equals(targetUrl))
                    .findFirst()
                    .orElseThrow(() -> new RouterException("未找到对应的路由配置: " + originUrl + " " + method + " " + contentType));
            routeAttribute.setHandler(handler);
        }
    }

    public void transit(HttpServletRequest request, HttpServletResponse response, RequestMethod method, String contentType) {
        String requestUrl = request.getRequestURI().replaceFirst("/transit", "");
        log.debug("requestUrl: {}, method: {}, contentType: {}", requestUrl, method, contentType);
        log.info("中转处理: {} - {}: {}", requestUrl, method, contentType);
        List<RouteAttribute> routeAttributes = routeMap.get(requestUrl);
        if (routeAttributes == null || routeAttributes.isEmpty()) {
            throw new RouterException("未找到对应的路由配置: " + requestUrl);
        }
        for (RouteAttribute routeAttribute : routeAttributes) {
            log.debug("routeAttribute: {}", routeAttribute);
            if (routeAttribute.getMethod().equals(method) && routeAttribute.getContentType().equals(contentType)) {
                try {
                    routeAttribute.getHandler().apply(new HttpServletMethod(request, response));
                    // 跳转到目标地址
                    response.sendRedirect(routeAttribute.getTargetUrl());
                    return;
                } catch (Exception e) {
                    throw new RouterException("处理请求时发生错误: " + e.getMessage());
                }
            }
        }
        throw new RouterException("没有找到对应的处理方法：" + method + " " + contentType + " " + requestUrl);
    }

    public void printAllRoutes() {
        for (String url : routeMap.keySet()) {
            List<RouteAttribute> routeAttributes = routeMap.get(url);
            if (routeAttributes == null || routeAttributes.isEmpty()) {
                log.debug("没有找到对应的路由配置: {}", url);
                continue;
            }
            for (RouteAttribute routeAttribute : routeAttributes) {
                log.debug("路由配置: {} {} {} {}", url, routeAttribute.getMethod(), routeAttribute.getContentType(), routeAttribute.getTargetUrl());
            }
        }
    }
}
